/*
 * buzzer.c
 *
 *  Created on: Jul 8, 2025
 *      Author: 天溯研发-WD
 */


#include "stm32f1xx_hal.h"

/* 定义蜂鸣器控制参数 */
#define BUZZER_GPIO_PORT      GPIOA
#define BUZZER_GPIO_PIN       GPIO_PIN_7
#define BUZZER_ACTIVE_STATE   GPIO_PIN_SET    // 高电平触发有源蜂鸣器

/* 蜂鸣器状态枚举 */
typedef enum {
    BUZZER_IDLE,        // 空闲状态
    BUZZER_PLAYING,     // 播放状态
    BUZZER_PAUSED,      // 暂停状态
} BuzzerState;

/* 蜂鸣器控制结构体 */
typedef struct {
    BuzzerState state;            // 当前状态
    uint32_t beep_time;           // 鸣叫时间(ms)
    uint32_t pause_time;          // 暂停时间(ms)
    uint8_t repeat;               // 重复次数
    uint8_t count;                // 当前计数
    uint32_t start_time;          // 开始时间戳
} BuzzerControl;

/* 全局蜂鸣器控制变量 */
BuzzerControl buzzer = {
    .state = BUZZER_IDLE,
    .beep_time = 200,
    .pause_time = 300,
    .repeat = 5,
    .count = 0,
    .start_time = 0
};

/* 初始化蜂鸣器 */
void Buzzer_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* 使能蜂鸣器引脚的GPIO时钟 */
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /* 配置蜂鸣器引脚为推挽输出 */
    GPIO_InitStruct.Pin = BUZZER_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(BUZZER_GPIO_PORT, &GPIO_InitStruct);

    /* 初始状态为静音 */
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, !BUZZER_ACTIVE_STATE);
}

/* 启动蜂鸣器（持续鸣叫） */
void Buzzer_On(void) {
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, BUZZER_ACTIVE_STATE);
    buzzer.state = BUZZER_PLAYING;
}

/* 关闭蜂鸣器（静音） */
void Buzzer_Off(void) {
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, !BUZZER_ACTIVE_STATE);
    buzzer.state = BUZZER_IDLE;
}

/* 启动间断鸣叫模式 */
void Buzzer_StartBeep(uint32_t beep_ms, uint32_t pause_ms, uint8_t repeat) {
    buzzer.beep_time = beep_ms;
    buzzer.pause_time = pause_ms;
    buzzer.repeat = repeat;
    buzzer.count = 0;
    buzzer.start_time = HAL_GetTick();

    Buzzer_On();  // 开始鸣叫
}

/* 在主循环中定期调用，处理蜂鸣器状态 */
void Buzzer_Process(void) {
    if (buzzer.state == BUZZER_IDLE) return;

    uint32_t current_time = HAL_GetTick();

    switch (buzzer.state) {
        case BUZZER_PLAYING:
            if (current_time - buzzer.start_time >= buzzer.beep_time) {
                Buzzer_Off();
                buzzer.start_time = current_time;
                buzzer.state = BUZZER_PAUSED;
            }
            break;

        case BUZZER_PAUSED:
            if (current_time - buzzer.start_time >= buzzer.pause_time) {
                buzzer.count++;

                if (buzzer.count >= buzzer.repeat && buzzer.repeat != 0) {
                    buzzer.state = BUZZER_IDLE;
                } else {
                    Buzzer_On();
                    buzzer.start_time = current_time;
                    buzzer.state = BUZZER_PLAYING;
                }
            }
            break;

        default:
            break;
    }
}
